package com.wyp.utils.redis;

import com.alibaba.fastjson.JSON;
import com.wyp.utils.redis.prekey.KeyPrefix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * 使用JedisPool进行获取到Jedis客户端，进行操作Redis
 * <p>
 * 设计思路--根据传入参数以及类型，前缀进行操作Redis
 *
 * @author: Oliver
 */
@Service
public class RedisService {
    @Autowired
    JedisPool jedisPool;

    /**
     * 获取单个对象
     *
     * @param prefix 前缀
     * @param key    key
     * @param clazz  类型class
     * @param <T>    泛型
     * @return 返回数据
     */
    public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            String value = jedis.get(realKey);
            T result = StringToBean(value, clazz);
            return result;
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * 判断是否存在
     *
     * @param prefix
     * @param key
     * @param <T>
     * @return
     */
    public <T> Boolean exists(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            Boolean exists = jedis.exists(realKey);
            return exists;
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * 增加一个
     *
     * @param prefix
     * @param key
     * @param <T>
     * @return
     */
    public <T> Long incr(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            Long incr = jedis.incr(realKey);
            return incr;
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * 减少一个
     *
     * @param prefix
     * @param key
     * @param <T>
     * @return
     */
    public <T> Long decr(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            return jedis.decr(realKey);

        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * 删除
     *
     * @param prefix
     * @param key
     * @param <T>
     * @return 是否删除
     */
    public <T> boolean delete(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            return jedis.del(realKey) > 0;
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * 存入redis
     *
     * @param prefix 前缀
     * @param key    key
     * @param value  要存放的信息
     * @param <T>
     * @return 返回是否成功
     */
    public <T> Boolean set(KeyPrefix prefix, String key, T value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String strResult = beanToString(value);
            //校验参数可行性
            if (strResult == null || strResult.length() <= 0) {
                return false;
            }

            String realKey = prefix.getPrefix() + key;
            int seconds = prefix.expireSeconds();
            if (seconds <= 0) {//没有过期时间
                jedis.set(realKey, strResult);
            } else {//有过期时间
                jedis.setex(realKey, seconds, strResult);
            }
            return true;
        } finally {
            returnToPool(jedis);
        }
    }

    /**
     * 将bean转换成String进行存放
     *
     * @param value value
     * @param <T>
     * @return String
     */
    public static  <T> String beanToString(T value) {
        if (value == null) {
            return null;
        }
        Class<?> clazz = value.getClass();
        if (clazz == int.class || clazz == Integer.class) {
            return "" + value;
        } else if (clazz == String.class) {
            return (String) value;
        } else if (clazz == long.class || clazz == Long.class) {
            return "" + value;
        } else {
            return JSON.toJSONString(value);
        }
    }


    /**
     * 将转换后存入redis的字符串取出来后转为原来对象
     *
     * @param value string
     * @param clazz 类型
     * @param <T>
     */
    public static  <T> T StringToBean(String value, Class<T> clazz) {
        if (value == null || value.length() <= 0 || clazz == null) {
            return null;
        }
        if (clazz == int.class || clazz == Integer.class) {
            return (T) Integer.valueOf(value);
        } else if (clazz == String.class) {
            return (T) value;
        } else if (clazz == long.class || clazz == Long.class) {
            return (T) Long.valueOf(value);
        } else {
            return JSON.toJavaObject(JSON.parseObject(value), clazz);
        }
    }

    /**
     * 操作完成后将连接返回到连接池
     *
     * @param jedis redis连接
     */
    private void returnToPool(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

}
